package com.lxw.redis.study.controller;


import com.lxw.redis.study.service.BitmapService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.RedisStringCommands;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Slf4j
@RestController
public class HelloBitMapController {
    @Autowired
    private BitmapService bitmapStatsService;
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    private static final String USER_MONTH_SIGN = "sign:uid:month:1:202306";
    private static final String weekSignAndKey = "week:sign:and";
    private static final String weekSignOrKey = "week:sign:or";

    @RequestMapping("/helloBitmap")
    public void helloBitmap() {
        setBit();
        getBit();
        bitCount();
        bitPos();
    }

    // 首签 累计签到 连续签到
    private void setBit() {
        bitmapStatsService.setBit(USER_MONTH_SIGN, 3, true);
        bitmapStatsService.setBit(USER_MONTH_SIGN, 6, true);
        bitmapStatsService.setBit(USER_MONTH_SIGN, 9, true);
        redisTemplate.expire(USER_MONTH_SIGN, 1, TimeUnit.DAYS);
    }


    private void getBit() {
        // 可不初始化(string) 不一定非要从0开始,可以用1代表1号
        Boolean bit3 = bitmapStatsService.getBit(USER_MONTH_SIGN, 3);
        log.info("3号签到情况:{}", bit3);
        Boolean bit6 = bitmapStatsService.getBit(USER_MONTH_SIGN, 6);
        log.info("6号签到情况:{}", bit6);
        Boolean bit9 = bitmapStatsService.getBit(USER_MONTH_SIGN, 9);
        log.info("9号签到情况:{}", bit9);
    }

    private void bitCount() {
        Long count = bitmapStatsService.bitCount(USER_MONTH_SIGN);
        log.info("累计签到{}天", count != null ? count : 0L);
    }


    private void bitPos() {
        Long pos = bitmapStatsService.bitPos(USER_MONTH_SIGN, true);
        log.info("首签{}号", pos);
    }


    @RequestMapping("/bitOp")
    public void bitOp() {
        // 1号用户7天全签到
        weekSign(1, true);
        // 2号用户周一没有签到
        weekSign(2, true);
        bitmapStatsService.setBit("week:sign:1", 2, false);
        // 3号用户只有周1签到
        bitmapStatsService.setBit("week:sign:1", 3, true);
        // 输出签到结果
        show();
        // 统计结果
        bitOpAnd();
        bitOpOr();
    }

    private void show() {
        int[] userIds = {1, 2, 3};
        List<StringBuilder> list = new ArrayList<>();
        for (String s : getWeekSignKey()) {
            StringBuilder sb = new StringBuilder();
            for (int userId : userIds) {
                Boolean bit = bitmapStatsService.getBit(s, userId);
                sb.append(bit ? "1\t" : "0\t");
            }
            list.add(sb);
        }
        for (StringBuilder sb : list) {
            System.out.println(sb);
        }
        System.out.println("----------------------");
        StringBuilder and = new StringBuilder();
        for (int userId : userIds) {
            Boolean bit = bitmapStatsService.getBit(weekSignAndKey, userId);
            and.append(bit ? "1\t" : "0\t");
        }
        System.out.println(and);
        System.out.println("----------------------");
        StringBuilder or = new StringBuilder();
        for (int userId : userIds) {
            Boolean bit = bitmapStatsService.getBit(weekSignOrKey, userId);
            or.append(bit ? "1\t" : "0\t");
        }
        System.out.println(or);
        for (int userId : userIds) {
            allSign(userId);
            anySign(userId);
        }
    }

    public String[] getWeekSignKey() {
        String[] keys = new String[7];
        // 按天记录 week:sign:1 周一签到情况,week:sign:2 周二签到情况...
        String userSignKey = "week:sign:${week}";
        for (int i = 1; i <= 7; i++) {
            String key = userSignKey.replace("${week}", String.valueOf(i));
            keys[i - 1] = key;
        }
        System.out.println(Arrays.toString(keys));
        return keys;
    }

    public void weekSign(int userId, boolean value) {
        String[] keys = getWeekSignKey();
        for (String key : keys) {
            System.out.println(key);
            bitmapStatsService.setBit(key, userId, value);
            redisTemplate.expire(key, 1, TimeUnit.DAYS);
        }
    }


    private void bitOpAnd() {
        // 周签统计结果
        bitmapStatsService.bitOp(RedisStringCommands.BitOperation.AND, weekSignAndKey, getWeekSignKey());
    }


    private void bitOpOr() {
        // 周签统计结果
        bitmapStatsService.bitOp(RedisStringCommands.BitOperation.OR, weekSignOrKey, getWeekSignKey());
    }

    private void allSign(int userId) {
        Boolean bit = bitmapStatsService.getBit(weekSignAndKey, userId);
        log.info("用户{}是否7天有签到过:{}", userId, bit);
        redisTemplate.expire(weekSignAndKey, 1, TimeUnit.DAYS);
    }

    private void anySign(int userId) {
        Boolean bit = bitmapStatsService.getBit(weekSignOrKey, userId);
        log.info("用户{}是否7天都签到过:{}", userId, bit);
        redisTemplate.expire(weekSignOrKey, 1, TimeUnit.DAYS);
    }


}
